package com.zhaozhaonews.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhaozhaonews.common.constants.WemediaConstants;
import com.zhaozhaonews.common.constants.WmNewsMessageConstants;
import com.zhaozhaonews.common.exception.CustomException;
import com.zhaozhaonews.model.common.dto.PageResponseResult;
import com.zhaozhaonews.model.common.dto.ResponseResult;
import com.zhaozhaonews.model.common.enums.AppHttpCodeEnum;
import com.zhaozhaonews.model.wemedia.dto.WmNewsDownOrUpDto;
import com.zhaozhaonews.model.wemedia.dto.WmNewsDto;
import com.zhaozhaonews.model.wemedia.dto.WmNewsPageReqDto;
import com.zhaozhaonews.model.wemedia.entity.WmMaterial;
import com.zhaozhaonews.model.wemedia.entity.WmNews;
import com.zhaozhaonews.model.wemedia.entity.WmNewsMaterial;
import com.zhaozhaonews.model.wemedia.entity.WmUser;
import com.zhaozhaonews.util.thread.WmThreadLocalUtil;
import com.zhaozhaonews.wemedia.mapper.WmNewsMapper;
import com.zhaozhaonews.wemedia.mapper.WmNewsMaterialMapper;
import com.zhaozhaonews.wemedia.service.WmMaterialService;
import com.zhaozhaonews.wemedia.service.WmNewsAutoScanService;
import com.zhaozhaonews.wemedia.service.WmNewsMaterialService;
import com.zhaozhaonews.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author WanJL
 * @since 2025-02-17
 */
@Service
@Slf4j
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Resource
    private WmNewsMaterialService wmNewsMaterialService;
    @Resource
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Resource
    private WmMaterialService wmMaterialService;
    @Resource
    private WmNewsAutoScanService wmNewsAutoScanService;
    @Resource
    private KafkaTemplate<String,String> kafkaTemplate;
    /**
     * 查询新闻
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult list(WmNewsPageReqDto dto) {
        //1、检查参数
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.checkParam();
        //获取当前登录用户的信息
        WmUser user = WmThreadLocalUtil.getUser();
        //判断是否登录
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2、分页查询
        IPage<WmNews> page = new Page<>(dto.getPage(),dto.getSize());
        LambdaQueryWrapper<WmNews> lqw = new LambdaQueryWrapper<>();
        //根据状态进行精确查询
        if (dto.getStatus() != null) {
            lqw.eq(WmNews::getStatus,dto.getStatus());
        }
        //根据频道精确查询
        if (dto.getChannelId() != null) {
            lqw.eq(WmNews::getChannelId,dto.getChannelId());
        }
        //时间范围查询
        if (dto.getBeginPubDate() != null&&dto.getEndPubDate() != null) {
            lqw.between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());
        }
        //关键字模糊查询
        if (StringUtils.isNotBlank(dto.getKeyword())){
            lqw.like(WmNews::getTitle,dto.getKeyword());
        }
        page=page(page, lqw);

        //3、把结果返回
        ResponseResult result = new PageResponseResult((int)page.getCurrent(),(int)page.getSize(),(int)page.getTotal());
        result.setData(page.getRecords());

        return result;
    }

    @Override
    public ResponseResult submitNews(WmNewsDto dto) {
        //1、参数判断
        if (dto == null||dto.getContent()==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2、保存或修改新闻
        WmNews wmNews = new WmNews();
        //复制所有属性
        BeanUtils.copyProperties(dto,wmNews);
        //2.2 设置封面图片
        if (dto.getImages() != null&&dto.getImages().size() > 0) {
            String imageStr = StringUtils.join(dto.getImages(), ",");
            wmNews.setImages(imageStr);
        }
        //如果自动设置封面，则参数为-1
        if (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO))
            wmNews.setType(null);

        //保存或修改新闻
        saveOrUpdateNews(wmNews);

        //判断是否保存为草稿，如果是草稿就结束当前方法结果
        if (dto.getStatus().equals(WmNews.Status.NORMAL.getCode()))
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

        //如果不是草稿，就保存新闻内容图片和素材的关系
        //获取新闻内容中的图片信息
        List<String> materialList= ectractUrlInfo(dto.getContent());
        //保存新闻内容图片和素材的关系
        saveRelativeInfoForContent(materialList,wmNews.getId());
        //如果布局是自动的，也是需要匹配封面图片
        saveRelativeInfoForCover(dto,wmNews,materialList);

        //审核新闻
        wmNewsAutoScanService.autoScanWmNews(wmNews.getId());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 新闻的上下架
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDownOrUpDto dto) {
        //1、检查参数
        if (dto == null||dto.getId()==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2、查询新闻
        WmNews wmNews = getById(dto.getId());
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"新闻不存在");
        }
        //3、判断新闻是否已发布
        if (!wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"当前新闻不是发布状态，不能上下架");
        }
        System.out.println("上下架状态----》"+dto.getEnable());
        //4、修改新闻的enable
        if (dto.getEnable()!=null&&dto.getEnable()>-1&&dto.getEnable()<2) {
            lambdaUpdate()
                    .set(WmNews::getEnable,dto.getEnable())
                    .eq(WmNews::getId,dto.getId()).update();
        }

        //5、通过kafka异步通知article端修改新闻配置
        if (wmNews.getArticleId()!=null){
            Map<String,Object> map=new HashMap<>();
            map.put("articleId",wmNews.getArticleId());
            map.put("enable",dto.getEnable());
            //把新闻id和上架下架的状态作为消息通知给article端
            kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,JSON.toJSONString(map));
            log.info("发送通知----》");
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    /**
     * 如果布局是自动的，需要保存封面图片和素材的关系
     * @param dto
     * @param wmNews
     * @param materialList
     */
    private void saveRelativeInfoForCover(WmNewsDto dto, WmNews wmNews, List<String> materialList) {
        List<String> images = dto.getImages();

        if (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) {

            if (materialList.size()>=3){//多图
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
                //把前三张图片作为封面图片
                images = materialList.stream().limit(3).collect(Collectors.toList());

            }else if (materialList.size()>=1&&materialList.size()<3){//单图
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
                images = materialList.stream().limit(1).collect(Collectors.toList());
            }else {//无图
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }
            //修改新闻
            if (images!=null && images.size()>0){
                wmNews.setImages(StringUtils.join(images,","));
            }
            updateById(wmNews);

        }
        if (images!=null && images.size()>0){
            saveRelativeInfo(images,wmNews.getId(),WemediaConstants.WM_CONTENT_REFERENCE);
        }
    }

    /**
     * 保存新闻内容图片和素材的关系
     * @param materialList
     * @param id
     */
    private void saveRelativeInfoForContent(List<String> materialList, Integer id) {
        saveRelativeInfo(materialList,id,WemediaConstants.WM_CONTENT_REFERENCE);
    }
    private void saveRelativeInfo(List<String> materialList, Integer id,Short type){
        if (materialList!=null&&materialList.size()>0&&!materialList.isEmpty()) {
            //通过图片的URL查询素材id
            List<WmMaterial> dbMaterialList = wmMaterialService.list(
                    Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, materialList)
            );
            if (dbMaterialList==null||dbMaterialList.size()<=0)
                throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);
            if (materialList.size()!=dbMaterialList.size())
                throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);

            List<Integer> idList = dbMaterialList.stream().map(WmMaterial::getId).collect(Collectors.toList());

            //批量保存ID
            wmNewsMaterialMapper.insertWmNewsMaterial(idList,id,type);
        }

    }
    /**
     * 获取新闻内容中图片信息
     * @param content
     * @return
     */
    private List<String> ectractUrlInfo(String content) {
        List<String> list = new ArrayList<>();
        List<Map> maps = JSON.parseArray(content, Map.class);
        for (Map map : maps) {
            if (map.get("type").equals("image")) {
                String imageUrl = (String) map.get("value");
                list.add(imageUrl);
            }
        }
        return list;
    }

    /**
     * 保存或修改新闻
     * @param wmNews
     */
    private void saveOrUpdateNews(WmNews wmNews) {
        //补全属性
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable((short)1);

        if (wmNews.getId() == null) {
            //保存
            save(wmNews);
        }else {
            //修改
            //先删除新闻图片和素材的关系，
            wmNewsMaterialService.remove(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId, wmNews.getId()));
            //再修改
            updateById(wmNews);
        }
    }
}
